﻿using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

namespace RpaDesigner.Frame
{
    public class ConnectorAdorner : Adorner
    {
        private PathGeometry _pathGeometry;
        private DesignerCanvas _designerCanvas;
        private Connector _sourceConnector;
        private Pen _drawingPen;

        private DesignerItem _hitDesignerItem;

        private DesignerItem HitDesignerItem
        {
            get => _hitDesignerItem;
            set
            {
                if (_hitDesignerItem != value)
                {
                    if (_hitDesignerItem != null)
                    {
                        _hitDesignerItem.IsDragConnectionOver = false;
                    }

                    _hitDesignerItem = value;
                    if (_hitDesignerItem != null)
                    {
                        _hitDesignerItem.IsDragConnectionOver = true;
                    }
                }
            }
        }

        private Connector _hitConnector;

        private Connector HitConnector
        {
            get => _hitConnector;
            set
            {
                if (_hitConnector != value)
                {
                    _hitConnector = value;
                }
            }
        }

        public ConnectorAdorner(DesignerCanvas canvas, Connector sourceConnector) : base(canvas)
        {
            this._designerCanvas = canvas;
            this._sourceConnector = sourceConnector;
            this._drawingPen = new Pen(Brushes.LightSlateGray, 1);
            this._drawingPen.LineJoin = PenLineJoin.Round;
            this.Cursor = Cursors.Cross;
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);

            if (HitConnector != null)
            {
                Connector sourceConnector = this._sourceConnector;
                Connector sinkConnector = this.HitConnector;
                Connection newConnection = new Connection(sourceConnector, sinkConnector);

                Panel.SetZIndex(newConnection, this._designerCanvas.Children.Count);

                this._designerCanvas.Children.Add(newConnection);

                HitConnector.BackgroundColor = Brushes.Transparent;
            }

            if (_hitDesignerItem != null)
            {
                _hitDesignerItem.IsDragConnectionOver = false;
            }

            if (IsMouseCaptured) ReleaseMouseCapture();

            var adornerLayer = AdornerLayer.GetAdornerLayer(this._designerCanvas);
            adornerLayer?.Remove(this);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                if (!this.IsMouseCaptured) this.CaptureMouse();

                if (HitConnector != null)
                {
                    HitConnector.BackgroundColor = Brushes.Transparent;
                }
                
                HitTesting(e.GetPosition(this));

                if (HitConnector != null)
                {
                    HitConnector.BackgroundColor = Brushes.Chocolate;
                }

                this._pathGeometry = GetPathGeometry(e.GetPosition(this));
                this.InvalidateVisual();
            }
            else
            {
                if (this.IsMouseCaptured) this.ReleaseMouseCapture();
            }
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);

            drawingContext.DrawGeometry(null, _drawingPen, _pathGeometry);

            // 绘制一个透明背景，用于响应鼠标事件
            drawingContext.DrawRectangle(Brushes.Transparent, null, new Rect(RenderSize));
        }

        private PathGeometry GetPathGeometry(Point position)
        {
            var geometry = new PathGeometry();

            Connector.ConnectorOrientation targetOrientation;
            if (HitConnector != null)
                targetOrientation = HitConnector.Orientation;
            else
                targetOrientation = Connector.ConnectorOrientation.None;

            List<Point> pathPoints =
                PathFinder.GetConnectionLine(_sourceConnector.GetInfo(), position, targetOrientation);

            if (pathPoints.Count > 0)
            {
                PathFigure figure = new PathFigure();
                figure.StartPoint = pathPoints[0];
                pathPoints.Remove(pathPoints[0]);
                figure.Segments.Add(new PolyLineSegment(pathPoints, true));
                geometry.Figures.Add(figure);
            }

            return geometry;
        }

        private void HitTesting(Point hitPoint)
        {
            var hitConnectorFlag = false;
            var hitObject = _designerCanvas.InputHitTest(hitPoint) as DependencyObject;

            while (hitObject != null
                   && hitObject != _sourceConnector.ParentDesignerItem
                   && hitObject.GetType() != typeof(DesignerCanvas))
            {
                if (hitObject is Connector)
                {
                    HitConnector = hitObject as Connector;
                    HitConnector.BackgroundColor = Brushes.Chocolate;
                    hitConnectorFlag = true;
                }

                if (hitObject is DesignerItem)
                {
                    HitDesignerItem = hitObject as DesignerItem;

                    if (!hitConnectorFlag)
                    {
                        HitConnector = null;
                    }

                    return;
                }

                hitObject = VisualTreeHelper.GetParent(hitObject);
            }

            HitConnector = null;
            HitDesignerItem = null;
        }
    }
}